#include "Reflectable.h"
#include <iostream>
using namespace std;

namespace noria {

	class MarshalImpl final
	{
	//public:
	//	MarshalImpl()
	//	{
	//		cout << "Marshal::ctor()" << endl;
	//	}
	//	~MarshalImpl()
	//	{
	//		cout << "Marshal::~ctor()" << endl;
	//	}
	public:
		IReflectable* Box(int value) const
		{
			return new Integer(value);
		}
		IReflectable* Box(long value) const
		{
			return new Long(value);
		}
		IReflectable* Box(double value) const
		{
			return new Double(value);
		}
		IReflectable* Box(bool value) const
		{
			return new Boolean(value);
		}
		IReflectable* Box(const char* value) const
		{
			return new AnsiString(value);
		}
		IReflectable* Box(const wchar_t* value) const
		{
			return new WideString(value);
		}

		void Unbox(const IReflectable& ref, int& value) const
		{
			value = static_cast<const Integer&>(ref).m_ptr;
		}
		void Unbox(const IReflectable& ref, long& value) const
		{
			value = static_cast<const Long&>(ref).m_ptr;
		}
		void Unbox(const IReflectable& ref, double& value) const
		{
			value = static_cast<const Double&>(ref).m_ptr;
		}
		void Unbox(const IReflectable& ref, bool& value) const
		{
			value = static_cast<const Boolean&>(ref).m_ptr;
		}
		void Unbox(const IReflectable& ref, const char*& value) const
		{
			value = static_cast<const AnsiString&>(ref).m_ptr;
		}
		void Unbox(const IReflectable& ref, const wchar_t*& value) const
		{
			value = static_cast<const WideString&>(ref).m_ptr;
		}

	private:
		template<typename T>
		class ValueType final : public IReflectable
		{
		public:
			ValueType(T value)
				: m_ptr(value)
			{
			}
		public:
			virtual void Dispose() override
			{
				delete this;
			}
			virtual const IType* const GetType() const override
			{
				return nullptr;
			}
			virtual IReflectable* Invoke(const char* name, IReflectable** args) override
			{
				return nullptr;
			}
		private:
			friend class MarshalImpl;
			T m_ptr;
		};

		typedef ValueType<bool> Boolean;
		typedef ValueType<int> Integer;
		typedef ValueType<long> Long;
		typedef ValueType<double> Double;
		typedef ValueType<float> Single;
		typedef ValueType<const char*> AnsiString;
		typedef ValueType<const wchar_t*> WideString;
	};
}